package com.zbycorp.generatecode.ui.base;

import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.EditableModel;
import com.zbycorp.generatecode.entity.TableInfo;
import com.zbycorp.generatecode.entity.Template;
import com.zbycorp.generatecode.service.SettingsStorageService;
import com.zbycorp.generatecode.utils.ModuleUtils;
import com.zbycorp.generatecode.utils.StringUtil;
import lombok.Data;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author YCL
 * @date 2023/3/28
 */
@Data
public class TableModel extends DefaultTableModel implements EditableModel {

    private JTable table;

    private TableInfo tableInfo;
    private Project project;
    private List<Template> templateList;

    public TableModel(Project project, TableInfo tableInfo, List<Template> templateList) {
        this.tableInfo = tableInfo;
        this.project = project;
        this.templateList = templateList;
        initColumn();
        refreshTemplateList();
        initTableData();
    }

    private void initColumn() {
        addColumn("Module");
        addColumn("Class");
        addColumn("Package");
    }

    public void initTableData() {
        // 删除所有列
        int size = getRowCount();
        for (int i = 0; i < size; i++) {
            super.removeRow(0);
        }
        for (Template template : this.templateList) {
            List<Object> values = new ArrayList<>();
            values.add(template.getModuleName());
            values.add(template.getClassName());
            values.add(template.getSavePackage());
            addRow(values.toArray());
        }
    }

    private void refreshTemplateList() {
        String tableName = this.tableInfo.getName();
        Map<String, List<Template>> templateMap = SettingsStorageService.getSettingStorage(project).getTemplateMap();

        List<Template> templates = new ArrayList<>();

        String defaultModule = null;
        Set<String> existModules = new HashSet<>();

        for (Module module : ModuleManager.getInstance(this.project).getModules()) {
            defaultModule = defaultModule == null ? module.getName() : defaultModule;
            String moduleName = module.getName();
            int lastIndexOf = moduleName.lastIndexOf("-");
            if (lastIndexOf == -1) {
                continue;
            }
            VirtualFile sourcePath = ModuleUtils.getSourcePath(module);
            String tk = moduleName.substring(lastIndexOf + 1);
            if (templateMap.containsKey(tk)) {
                existModules.add(tk);
                List<Template> templateList = templateMap.get(tk);
                templateList.forEach(item -> {
                    item.setModuleName(moduleName);
                    if ("entity".equals(item.getDefaultName())) {
                        item.setClassName(tableName);
                    } else {
                        item.setClassName(tableName + item.getDefaultName());
                    }
                    if (StringUtil.isNotEmpty(item.getDomainPackage())) {
                        item.setSavePackage(String.format("%s.%s.%s", item.getDefinedPackage(), item.getDefaultPackage(), item.getDomainPackage()));
                    } else {
                        item.setSavePackage(String.format("%s.%s", item.getDefinedPackage(), item.getDefaultPackage()));
                    }
                    item.setSavePath(sourcePath.getPath());
                });
                templates.addAll(templateList);
            }
        }

        // 不存在的模块，使用默认模块
        Map<String, List<Template>> notExistModules = templateMap.entrySet().stream()
                .filter(item -> !existModules.contains(item.getKey()))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        String finalDefaultModule = defaultModule;
        notExistModules.forEach((key, value) -> {
            value.forEach(item -> {
                item.setModuleName(finalDefaultModule);
                if ("entity".equals(item.getDefaultName())) {
                    item.setClassName(tableName);
                } else {
                    item.setClassName(tableName + item.getDefaultName());
                }
                if (StringUtil.isNotEmpty(item.getDomainPackage())) {
                    item.setSavePackage(String.format("%s.%s.%s", item.getDefinedPackage(), item.getDefaultPackage(), item.getDomainPackage()));
                } else {
                    item.setSavePackage(String.format("%s.%s", item.getDefinedPackage(), item.getDefaultPackage()));
                }
                item.setSavePath(ModuleUtils.getSourcePath(ModuleManager.getInstance(this.project).getModules()[0]).getPath());
            });
            templates.addAll(value);
        });

        this.templateList.clear();
        this.templateList.addAll(templates.stream().sorted(Comparator.comparing(Template::getModuleName)).collect(Collectors.toList()));
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        Template template = this.templateList.get(row);
        if (template == null) {
            return;
        }
        //module、class名暂不允许修改
        if (column < 2) {
            return;
        }

        switch (column) {
            case 0:
                String moduleName = (String) aValue;
                // 列名不允许为空
                if (StringUtil.isEmpty(moduleName)) {
                    return;
                }
                // 已存在重名不允许修改
                boolean existsName = this.templateList.stream().anyMatch(item -> Objects.equals(item.getModuleName(), moduleName));
                if (existsName) {
                    return;
                }
                template.setModuleName(moduleName);
                break;
            case 1:
                String className = (String) aValue;
                // 列名不允许为空
                if (StringUtil.isEmpty(className)) {
                    return;
                }
                // 已存在重名不允许修改
                boolean existsClass = this.templateList.stream().anyMatch(item -> Objects.equals(item.getModuleName(), className));
                if (existsClass) {
                    return;
                }
                template.setClassName(className);
                break;
            case 2:
                String packageName = (String) aValue;
                // 列名不允许为空
                if (StringUtil.isEmpty(packageName)) {
                    return;
                }
                template.setSavePackage(packageName);
                break;
            default:
                return;
        }

        super.setValueAt(aValue, row, column);
    }

    @Override
    public void addRow() {
    }

    @Override
    public void removeRow(int row) {
        // 批量删除
        int[] selectedRows = this.table.getSelectedRows();
        List<Template> deletedList = Arrays.stream(selectedRows)
                .mapToObj(this.templateList::get)
                .collect(Collectors.toList());
        this.templateList.removeAll(deletedList);
        this.initTableData();
    }

    @Override
    public void exchangeRows(int oldIndex, int newIndex) {
    }

    @Override
    public boolean canExchangeRows(int oldIndex, int newIndex) {
        return false;
    }
}
